﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using _01_Tower4._0.GameFrame.Manager;
using _01_Tower4._0.Interface;
using _01_Tower4._0.Scene;
using _01_Tower4._0.Tool;
using static _01_Tower4._0.GameFrame.Game;

namespace _01_Tower4._0.GameFrame.System
{
    internal class DialogSystem
    {
        struct Data
        {
            public int id;
            public bool isOption;
            public string content1;
            public int nextId1;
            public string content2;
            public int nextId2;
        }

        enum State
        {
            None,
            UpRoll,
            DownRoll,
            NextDialog
        }

        Data[] datas;
        int offsetX, offsetY;
        int row, col;
        long lastTime, currentTime;
        int selected;
        ConsoleKeyInfo key;
        Data currentData;
        State state;
        public Map map;
        IScene scnen;

        public bool IsOpen { get; set; }
        public event Action overDialog;
        public event Action selection1;
        public event Action selection2;

        public DialogSystem(IScene scene)
        {
            Console.CursorVisible = false;
            LoadData();
            offsetX = 5;
            offsetY = 31;
            row = 6;
            col = 40;
            currentData = GetData(0);
            IsOpen = true;

            this.scnen = scene;
            string[] paths = { "../../../Map/KingHalfBody.csv", "../../../Map/MaoHalfBodyDs.csv" };
            map = new Map(paths, 76, 30, 0, 0, scene);
        }

        // 从文件中读取对话数据并存入数组
        void LoadData()
        {
            string fileName = "../../../Data/DialogData.txt";
            if (File.Exists(fileName))
            {
                // 读取文件, 这里using表示只在这里读取(使用？)，出了之后释放？以免内存泄漏
                using (StreamReader sr = new StreamReader(fileName))
                {
                    string data = sr.ReadToEnd();
                    // 字符串分割 Split, 这里的文本中用",""换行"分离
                    string[] lines = data.Split('\n'); // 分隔的也可使字符串
                    // 根据数据行数 分配内存空间
                    datas = new Data[lines.Length - 1];
                    for (int i = 0; i < datas.Length; i++)
                    {
                        string[] elements = lines[i + 1].Split('|');
                        datas[i].id = int.Parse(elements[0]);
                        datas[i].isOption = elements[1] == "true";
                        datas[i].content1 = elements[2];
                        datas[i].nextId1 = int.Parse(elements[3]);
                        if (!datas[i].isOption) continue;
                        datas[i].content2 = elements[4];
                        datas[i].nextId2 = int.Parse(elements[5]);
                    }
                };
            }
        }

        // 根据id获取对话数据
        Data GetData(int id)
        {
            Data data = new Data();

            for (int i = 0; i < datas.Length; i++)
            {
                if (datas[i].id == id)
                {
                    data = datas[i];
                    break;
                }
            }

            return data;
        }

        void Clear()
        {
            for (int i = 0; i < row; i++)
            {
                for (int j = 0; j < col; j++)
                {

                    MyPrint("  ", offsetX + j, offsetY + i);
                }
            }
        }

        void PrintFrame()
        {
            for (int i = 0; i < row; i++)
            {
                for (int j = 0; j < col; j++)
                {
                    string temp = "";
                    if (i == 0 && j == 0)
                    {
                        temp = "┌";
                    }
                    else if (i == 0 && j == col - 1)
                    {
                        temp = "┐";
                    }
                    else if (i == row - 1 && j == 0)
                    {
                        temp = "└";
                    }
                    else if (i == row - 1 && j == col - 1)
                    {
                        temp = "┘";
                    }
                    else if (i == 0 || i == row - 1)
                    {
                        temp = "─";
                    }
                    else if (j == 0 || j == col - 1)
                    {
                        temp = "│";
                    }
                    MyPrint(temp, offsetX + j, offsetY + i);
                }
            }
        }

        void PrintText()
        {
            if (!currentData.isOption)
            {
                if(SceneMap1.dsTarget == "fk")
                {
                    map.ChangePicture(0);
                    map.Render();
                    Utility.MyPrint("国王", 45, offsetY-1, ConsoleColor.Yellow);
                }
                if (SceneMap1.dsTarget == "m")
                {
                    map.ChangePicture(1);
                    map.Render();
                    Utility.MyPrint("魔王", 45, offsetY - 1, ConsoleColor.Yellow);
                }
                if (SceneMap1.dsTarget == "rk")
                {
                    map.ChangePicture(0);
                    map.Render();
                    Utility.MyPrint("国王", 45, offsetY - 1, ConsoleColor.Yellow);
                }
                if (SceneMap1.dsTarget == "n1")
                {
                    Utility.MyPrint("老者", 45, offsetY - 1, ConsoleColor.Blue);
                }
                if (SceneMap1.dsTarget == "n2")
                {
                    Utility.MyPrint("青年", 45, offsetY - 1, ConsoleColor.Green);
                }
                if (SceneMap1.dsTarget == "p")
                {
                    Utility.MyPrint("牧师", 45, offsetY - 1, ConsoleColor.Green);
                }
                string str = currentData.content1;
                Console.SetCursorPosition((offsetX + 2) * 2, offsetY + 2);
                for (int i = 0; i < str.Length; i++)
                {

                    if (i == 36)
                    {
                        Console.SetCursorPosition((offsetX + 2) * 2, offsetY + 3);
                    }
                    Console.Write(str[i].ToString());
                    Thread.Sleep(10);
                }
            }
            else
            {
                Utility.MyPrint("Hero", 45, offsetY - 1);
                string str = currentData.content1;
                Console.SetCursorPosition((offsetX + 2) * 2, offsetY + 2);
                Console.ForegroundColor = selected == 0 ? ConsoleColor.Red : ConsoleColor.White;
                for (int i = 0; i < str.Length; i++)
                {
                    Console.Write(str[i].ToString());
                    Thread.Sleep(10);
                }
                str = currentData.content2;
                Console.SetCursorPosition((offsetX + 2) * 2, offsetY + 3);
                Console.ForegroundColor = selected == 1 ? ConsoleColor.Red : ConsoleColor.White;
                for (int i = 0; i < str.Length; i++)
                {
                    Console.Write(str[i].ToString());
                    Thread.Sleep(10);
                }
                Console.ResetColor();
            }

        }

        public void Render()
        {
            if (!IsOpen)
            {
                SceneManager.sceneName = "SceneMap1";
                return;
            }
            PrintFrame();
            PrintText();
            
        }



        void MyPrint(string str, int x, int y, ConsoleColor color = ConsoleColor.White)
        {
            Console.SetCursorPosition(x * 2, y);
            Console.ForegroundColor = color;
            Console.Write(str);
            Console.ResetColor();
        }

        public void StartDialog(int id)
        {
            SceneManager.sceneName = "SceneDialog";
            currentData = GetData(id);
            IsOpen = true;
            Console.SetWindowSize(100, 40);
        }

        void UpRoll()
        {
            if (!IsOpen)
            {
                return;
            }
            if (!currentData.isOption)
                return;
            selected--;
            if (selected < 0)
            {
                selected = 1;
            }
        }

        void DownRoll()
        {
            if (!IsOpen)
            {
                return;
            }
            if (!currentData.isOption)
                return;
            selected++;
            if (selected > 1)
            {
                selected = 0;
            }
        }

        void NextDialog()
        {
            if (!IsOpen)
            {
                return;
            }
            int nextId = 0;
            if (currentData.isOption)
            {
                nextId = selected == 0 ? currentData.nextId1 : currentData.nextId2;
            }
            else
            {
                nextId = currentData.nextId1;
            }

            if (nextId < 0)
            {
                if (nextId == -2)
                {
                    selection1?.Invoke();
                }
                else if (nextId == -3)
                {
                    selection2?.Invoke();
                }

                ClearSelectionEvent();
                IsOpen = false;
                overDialog.Invoke();
                Console.SetWindowSize(100, 32);
                Console.SetBufferSize(120, 60);
                Console.Clear();
            }

            currentData = GetData(nextId);
            selected = 0;
            Clear();
        }

        void ClearSelectionEvent()
        {
            selection1 -= selection1;
            selection2 -= selection2;
        }

        public void Input()
        {
            state = State.None;
            if (InputSystem.Instance.IsKeyPressed(ConsoleKey.W))
            {
                state = State.UpRoll;
            }
            if (InputSystem.Instance.IsKeyPressed(ConsoleKey.S))
            {
                state = State.DownRoll;
            }
            if (InputSystem.Instance.IsKeyPressed(ConsoleKey.Enter))
            {
                state = State.NextDialog;
            }
        }

        public void Update()
        {
            switch (state)
            {
                case State.UpRoll:
                    UpRoll();
                    break;
                case State.DownRoll:
                    DownRoll();
                    break;
                case State.NextDialog:
                    NextDialog();
                    break;
            }
        }
    }
}
